<template>
    <div style="padding:20px;min-width:1000px">
        <div style="display:flex;border:1px solid #ccc;padding:10px;margin-bottom:10px">
            <el-select v-model="state.requestData.groupId" filterable @change="handleCheckRuleId" style="margin-right:8px;width:200px" size="mini">
                <el-option
                    v-for="item in state.checkGroup"
                    :key="item.groupId"
                    :value="item.groupId"
                    :label="item.groupId + '-' + (item.groupName || '')"
                ></el-option>
            </el-select>
            <RiskCustomSelect
                :selectKeys="state.requestData.ruleIds"
                :dataSource="state.checkRule"
                showSelectAll="true"
                :showSearch="state.checkRule && state.checkRule.length != 0"
                :key="'renderCheckRuleNum' + renderCheckRuleNum"
                @customSelectReturn="customSelectReturn"
            ></RiskCustomSelect>
            <!-- <el-checkbox-group v-model="valueTest" style="display:flex;flex-direction:column;padding-left:6px" size="mini">
                <el-checkbox v-for="item in state.checkRule" :key="item.dictKey" :label="item.dictKey">
                    {{ item.dictKey + '  ' + item.dictKeyName }}</el-checkbox
                >
            </el-checkbox-group> -->
            <el-button
                :disabled="state.process.state !== 'NO_CALCULATE'"
                style="margin:0 10px"
                @click="handleClickButton('start')"
                size="mini"
                type="primary"
                >开始计算</el-button
            >
            <el-button @click="handleClickButton('stop')" size="mini" type="danger">停止</el-button>
        </div>
        <!-- <div style="margin-top:5px">
            <el-radio-group :value="state.process.state" finish-status="success">
                <el-radio label="NO_CALCULATE"
                    ><span :style="{ 'font-weight': elstate.process.state === 'NO_CALCULATE' ? '700' : '' }">未计算</span>
                </el-radio>
                <el-radio label="DATA_INIT"
                    ><span :style="{ 'font-weight': elstate.process.state === 'DATA_INIT' ? '700' : '' }">数据初始化</span>
                </el-radio>
                <el-radio label="IN_CALCULATE"
                    ><span :style="{ 'font-weight': elstate.process.state === 'IN_CALCULATE' ? '700' : '' }">计算中</span>
                </el-radio>
                <el-radio label="CALCULATE_FINISH"
                    ><span :style="{ 'font-weight': elstate.process.state === 'CALCULATE_FINISH' ? '700' : '' }">计算完成</span></el-radio
                >
                <span
                    :style="{ display: state.process.state === 'NO_CALCULATE' && state.process.errorMessage ? '' : 'none' }"
                    style="margin-left: 50px, font-weight: 700, color: red"
                >
                    {{ process.errorMessage }}
                </span>
            </el-radio-group>
        </div> -->
        <ExecuteResult :process="state.process" />
        <!-- :style="{ display: state.process.state === 'CALCULATE_FINISH' ? '' : 'none' } -->
        <div v-if="state.process.state === 'CALCULATE_FINISH'">
            <div style="overflow:auto;height:calc(100vh -200px);border:1px solid rgb(202,202,202)">
                <el-row>
                    <el-col :key="renderCount" :span="9" style="padding:10px 5px;height:calc(100vh - 200px);border-right:1px solid rgb(202,202,202)">
                        <div style="font-weight:700">勾稽结果饼状图</div>
                        <el-divider />
                        <div ref="leftChart" style="min-width: 400px;min-height:300px;"></div>
                        <div style="position: absolute; top: 314px;left: 155px;color: rgba(0,0,0,.65);">
                            勾稽结果统计
                        </div>
                        <!-- @click="handleEchartClick" -->
                    </el-col>
                    <el-col :span="15" style="padding: 10px 5px; height: calc(100vh - 200px)">
                        <div style="font-weight:700">勾稽结果列表</div>
                        <risk-table
                            :msg="listMsg"
                            :key="renderCount"
                            style="padding:10px 0"
                            @getList="getTableData"
                            @handleDetailsBtn="handleDetailsBtn"
                        ></risk-table>
                    </el-col>
                </el-row>
                <el-dialog title="详情列表" :visible.sync="detailsVisible" width="50%">
                    <el-table :data="tableDetalis" style="width: 100%" border tooltip-effect="dark">
                        <el-table-column prop="checkResult" label="执行结果" width="100">
                            <template slot-scope="scope">
                                <span :style="{ color: scope.row.checkResult == '1' ? '#ffb883' : scope.row.checkResult == '2' ? '#ff0000' : '' }">
                                    {{ scope.row.checkResult == '1' ? '警告' : scope.row.checkResult == '2' ? '错误' : '--' }}
                                </span>
                            </template>
                        </el-table-column>
                        <el-table-column prop="ruleId" label="规则序号" width="100"> </el-table-column>
                        <el-table-column prop="targetCode" label="指标编号" width="100"> </el-table-column>
                        <el-table-column prop="targetType" label="指标类型" width="100"> </el-table-column>
                        <el-table-column prop="ruleName" label="规则名称"> </el-table-column>
                    </el-table>
                    <span slot="footer" class="dialog-footer">
                        <el-button @click="detailsVisible = false">取 消</el-button>
                        <el-button type="primary" @click="detailsVisible = false">确 定</el-button>
                    </span>
                </el-dialog>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import { getConfigItem, getCurrentPageData, GunDataGzip, StringToBase64 } from '@/utils/tools';
import { getUser } from '@/utils/user-util';
import { Component, Vue } from 'vue-property-decorator';
import ExecuteResult from './check-execute/execute-result.vue';
import * as ECharts from 'echarts';
import RiskTable from '@/common/components/risk-table.vue';
import RiskCustomSelect from '@/common/components/risk-custom-select.vue';

export interface pages {
    total?: number;
    pageSize?: number;
    currentPage?: number;
}
@Component({
    name: 'CheckExecute',
    components: { ExecuteResult, RiskTable, RiskCustomSelect },
})
export default class CheckExecute extends Vue {
    BASE_URL_WS = getConfigItem('BASE_URL_WS');
    private valueTest: any[] = [];
    private listMsg = {
        returnData: {},
        dataKey: 'list',
        title: [
            {
                name: '执行结果',
                val: 'checkResult',
                minWidth: 100,
                type: 'status',
                statusKV: { '1': '警告', '2': '错误' },
                prop: 'checkResultColor',
                // ...new TableHeaderSearch({ fieldName: ['checkResult'] }).getColumnSearchProps(),
            },
            {
                name: '规则序号',
                val: 'ruleId',
                minWidth: 100,
                // ...new TableHeaderSearch({ fieldName: ['ruleId'] }).getColumnSearchProps(),
            },
            {
                name: '指标编号',
                val: 'targetCode',
                minWidth: 100,
                // ...new TableHeaderSearch({ fieldName: ['targetCode'] }).getColumnSearchProps(),
            },
            {
                name: '指标类型',
                val: 'targetType',
                minWidth: 100,
                // ...new TableHeaderSearch({ fieldName: ['targetType'] }).getColumnSearchProps(),
            },
            {
                name: '指标名称',
                val: 'targetName',
                minWidth: 100,
                // ...new TableHeaderSearch({ fieldName: ['targetName'] }).getColumnSearchProps(),
            },
            {
                name: '规则来源',
                val: 'ruleSource',
                minWidth: 100,
                // ...new TableHeaderSearch({ fieldName: ['ruleSource'] }).getColumnSearchProps(),
            },
            {
                name: '规则类型',
                val: 'ruleType',
                minWidth: 100,
                type: 'func',
                funcBody: value => this.name.ruleType[value],
                // ...new TableHeaderSearch({ fieldName: ['ruleType'] }).getColumnSearchProps(),
            },
            {
                name: '规则名称',
                val: 'ruleName',
                minWidth: 120,
                // ...new TableHeaderSearch({ fieldName: ['ruleName'] }).getColumnSearchProps(),
            },
            {
                name: '操作',
                type: 'detailsBtn',
                btns: [{ title: '查看详情', type: 'primary', icon: 'el-icon-view' }],
                width: '60px',
            },
        ],
        checked: { on: false, option: false },
        hidePage: false,
        // maxHeight: '400px',
    };
    state = {
        // 勾稽组下拉框数据
        checkGroup: [],
        // 勾稽组下拉
        checkRule: [],
        // 勾稽请求数据
        requestData: {
            groupId: '',
            ruleIds: [],
        },
        // 勾稽实时结果
        process: {
            state: '',
            calculateStartDate: '',
            calculateEndDate: '',
            totalAmount: 0,
            errorAmount: 0,
            warningAmount: 0,
            checkResultBOS: [],
        },
        // 表格数据
        tableDataSource: [],
    };
    name = {
        // 规则列表
        tableData: [],
        webSocket: null, // 状态
        renderCount: 1, // 表格渲染状态
        ruleType: {
            '1': '表数据量配置',
            '2': '关联关系一对一配置',
            '3': '关联关系一对多配置',
            '4': '字段字典配置',
            '5': '字段日期配置',
            '6': '字段时间配置',
            '7': '字段非NULL配置',
            '8': '自定义sql配置',
            '9': '存储过程',
        },
        // 备份数据
        tempData: [],
    };
    private renderCheckRuleNum: number = 0;
    private paging: pages = {
        total: 0,
        pageSize: 25,
        currentPage: 1,
    };

    // 列表详情弹窗
    private detailsVisible: boolean = false;

    // 列表详情数据
    private tableDetalis: [];

    // 表格显示数据
    private tableDataSourceTemp: any[] = [];

    TimeSendMessage = null;
    async mounted() {
        await this.getCheckGroup();
        this.getCalcStatus();
        this.initWebsocketConnect();
    }

    // 渲染表格
    private leftChartInit(): void {
        if (this.$refs.leftChart) {
            ECharts.init(this.$refs.leftChart).setOption({
                tooltip: {
                    trigger: 'item',
                    formatter: param => {
                        return this.handleToolipInfo(param.data.customType, param.data.value);
                    },
                },
                legend: {
                    bottom: 0,
                    left: 'center',
                    data: ['成功', '警告', '错误'],
                },
                color: ['#87D068', '#FFA500', '#D53A35'],
                series: [
                    {
                        name: '勾稽结果',
                        type: 'pie',
                        radius: '65%',
                        data: [
                            {
                                value: this.state.process.totalAmount - this.state.process.warningAmount - this.state.process.errorAmount,
                                name: '成功',
                                customType: '0',
                            },
                            { value: this.state.process.warningAmount, name: '警告', customType: '1' },
                            { value: this.state.process.errorAmount, name: '错误', customType: '2' },
                        ],
                    },
                ],
            });
        }
    }

    /**
     * 鼠标悬停查看echart
     */
    handleToolipInfo(type, count) {
        let result = Math.round((count / this.state.process.totalAmount) * 10000) / 100.0 + '%';
        return `<tr>
                    <td>${result}</td>
                </tr>`;
    }

    // 查询计算引擎状态
    private getCalcStatus(): void {
        // 获取勾稽规则计算状态
        this.$axios.get('/checkResult/status').then((returnValue: any) => {
            if (returnValue.checkResultBOS && returnValue.checkResultBOS.length > 0) {
                returnValue.checkResultBOS.forEach(item => {
                    // 指标类型
                    // boundCode有值代表指标类型是范围 enCalFacCode有值代表指标类型是因子
                    item.targetType = item.enCalFacCode ? '因子' : item.boundCode ? '范围' : '';
                    // 指标编号
                    item.targetCode = item.enCalFacCode ? item.enCalFacCode : item.boundCode;
                    // 指标名称
                    item.targetName = item.enCalFacName ? item.enCalFacName : item.boundName;
                });
            }

            this.state.tableDataSource = returnValue.checkResultBOS;
            this.state.tableDataSource.map(
                ele => (ele['checkResultColor'] = ele.checkResult === '1' ? 'orange' : ele.checkResult === '2' ? 'red' : '')
            );

            this.getTableData();
            this.state.process = returnValue || {};
            this.$nextTick(() => {
                this.leftChartInit();
            });
            this.name.tempData = returnValue.checkResultBOS;
            this.name.renderCount += 1;
        });
    }

    private getTableData(page?: any) {
        if (page) {
            this.paging = page;
        }
        this.tableDataSourceTemp = getCurrentPageData(this.state.tableDataSource, this.paging.currentPage, this.paging.pageSize);
        this.$set(this.listMsg.returnData, 'list', this.tableDataSourceTemp);
        this.listMsg.returnData['total'] = this.state.tableDataSource.length;
    }

    // 初始化websocket连接
    private initWebsocketConnect(): void {
        let Authentication = getUser().sessionId;
        let webSocket = new WebSocket(this.BASE_URL_WS + '/checkRule/socket/' + StringToBase64(Authentication));

        webSocket.onopen = e => {
            this.$notify({
                type: 'success',
                message: '连接成功',
                title: '数据引擎初始化消息服务已连接',
            });
        };

        webSocket.onmessage = e => {
            this.name.tempData = [];
            let process = JSON.parse(GunDataGzip(e.data));
            if (process.checkResultBOS != null && this.name.tableData.length > 0) {
                this.name.tableData.forEach(item => {
                    process.checkResultBOS.forEach(val => {
                        if (val.ruleId == item.ruleId) {
                            item.checkResult = val.checkResult;
                            // this.name.tempData.push(item);
                            this.name.tempData.push(val);
                        }
                    });
                });
            }
            this.name.tempData.forEach(item => {
                // 指标类型
                // boundCode有值代表指标类型是范围 enCalFacCode有值代表指标类型是因子
                item.targetType = item.enCalFacCode ? '因子' : item.boundCode ? '范围' : '';
                // 指标编号
                item.targetCode = item.enCalFacCode ? item.enCalFacCode : item.boundCode;
                // 指标名称
                item.targetName = item.enCalFacName ? item.enCalFacName : item.boundName;
            });
            this.state.tableDataSource = this.name.tempData;
            this.getTableData();
            this.state.process = process;
            this.$nextTick(() => {
                this.leftChartInit();
            });
            this.name.renderCount += 1;
        };

        webSocket.onclose = e => {
            this.$notify({
                type: 'warning',
                message: '断开连接',
                title: '勾稽规则初始化消息服务已断开',
            });
        };
        this.name.webSocket = webSocket;
        // 每隔1个小时发送一次消息 确保在使用nginx的情况下不会有断连的情况，同时约定nginx后台配置超时时间超过一个小时
        this.TimeSendMessage = setInterval(() => {
            try {
                webSocket.send('静态计算-发送WEBSOCKET心跳消息');
            } catch (e) {}
        }, 1000 * 60 * 60);
    }

    // 获取勾稽组数据
    private getCheckGroup(): void {
        this.$axios.get('/checkGroup/list').then((res: any) => {
            if (res) {
                this.state.checkGroup = res;
            }
        });
    }
    /**
     * 查询规则列表
     */
    private handleCheckRuleId(groupId: string) {
        this.state.requestData.ruleIds = [];
        if (groupId === undefined || groupId === '') {
            return [];
        }
        this.state.checkRule = [];
        this.$axios.get('/checkGroup/query/checkRule/' + groupId).then((response: any) => {
            this.name.tableData = response;
            for (let i = 0; i < response.length; i++) {
                this.state.checkRule.push({ dictKey: response[i].ruleId, dictKeyName: response[i].ruleName });
            }
            this.renderCheckRuleNum++;
        });
    }

    /**
     * 按钮事件
     */
    handleClickButton(action: string) {
        if (action === 'start') {
            let requestData = JSON.parse(JSON.stringify(this.state.requestData));
            this.$axios.post('/checkResult/start', requestData).then((res: any) => {
                this.state.process.state = 'IN_CALCULATE';
                this.name.renderCount += 1;
            });
        } else if (action === 'stop') {
            this.$axios.get('/checkResult/reset').then((res: any) => {
                this.state.process.state = 'NO_CALCULATE';
                this.name.renderCount += 1;
            });
        }
    }

    /**
     * 鼠标点击echart
     */
    handleEchartClick(value): void {
        // 成功默认查询全部
        if (value.data.customType === '0') {
            this.state.tableDataSource = this.name.tempData;
            return;
        }
        // 警告,失败
        if (this.state.process.checkResultBOS !== undefined) {
            this.state.tableDataSource = this.name.tempData.filter(item => item.checkResult === value.data.customType);
        }
    }

    // 多选框返回值
    private customSelectReturn(value: any[]): void {
        this.state.requestData.ruleIds = value;
    }

    // 勾稽规则结果列表详情按钮事件
    handleDetailsBtn(val) {
        this.detailsVisible = true;
        val.row.children.forEach(ele => {
            // 指标类型
            // boundCode有值代表指标类型是范围 enCalFacCode有值代表指标类型是因子
            ele.targetType = ele.enCalFacCode ? '因子' : ele.boundCode ? '范围' : '';
            // 指标编号
            ele.targetCode = ele.enCalFacCode ? ele.enCalFacCode : ele.boundCode;
        });
        this.tableDetalis = val.row.children;
    }
}
</script>
<style lang="scss" scoped>
/deep/ .el-divider--horizontal {
    margin: 10px 0;
}
/deep/ .vxe-table .vxe-table--body-wrapper.body--wrapper {
    height: calc(100vh - 350px);
}
</style>
